from pydantic import BaseModel
from typing import Generic, TypeVar, Type


T = TypeVar('T', bound='FunctionParameters')


class Tool:
    pass


class FunctionParameters(BaseModel):

    @staticmethod
    def __pop_key(key: str, obj: dict) -> None:
        """ In-place dropping the given key """
        if key in obj:
            obj.pop(key)

        for value in obj.values():
            if isinstance(value, dict):
                FunctionParameters.__pop_key(key, value)

    @classmethod
    def type_as_json(cls) -> object:
        ty = cls.model_json_schema()
        cls.__pop_key("title", ty)
        return ty


class NoInputParams(FunctionParameters):
    pass


class Function(Generic[T], Tool):

    def get_function_name(self) -> str:
        raise NotImplementedError

    def get_function_description(self) -> str:
        raise NotImplementedError

    def get_parameter_schema(self) -> Type[FunctionParameters]:
        raise NotImplementedError

    def call(self, args: T) -> str:
        raise NotImplementedError
